﻿using System;
using System.Linq;
using Ninject.Modules;
using System.Collections.Generic;

namespace NazTek.Core
{
    /// <summary>
    /// Encapsulates dependency map registration mechanism.
    /// </summary>
    public sealed class DependencyModule : IDisposable
    {
        /// <summary>
        /// Creates and stores underlying registration map.
        /// </summary>
        /// <param name="bindingPairs">Array of interface to implementation maps.</param>
        public DependencyModule(params KeyValuePair<Type, Type>[] bindingPairs)
        {
            Core = new DependencyModuleCore(bindingPairs);
        }
        /// <summary>
        /// Disposes underlying registration map.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
        }
        /// <summary>
        /// Gets/sets underlying registration map by interface.
        /// </summary>
        internal INinjectModule Core { get; private set; }
        /// <summary>
        /// Gets the concrete implementation of underlying registration map.
        /// </summary>
        internal NinjectModule ConcreteCore { get { return Core as NinjectModule; } }
        /// <summary>
        /// Wraps underlying dependency module.
        /// </summary>
        private sealed class DependencyModuleCore : NinjectModule
        {
            /// <summary>
            /// Sets dependency binding map.
            /// </summary>
            /// <param name="bindingPairs">Each key is interface and value is implementation.</param>
            internal DependencyModuleCore(params KeyValuePair<Type, Type>[] bindingPairs)
            {
                BindingPairs = bindingPairs;
            }
            /// <summary>
            /// Binds the <see cref="BindingPairs">dependency map</see> to the underlying container.
            /// </summary>
            public override void Load()
            {
                if (BindingPairs == null || BindingPairs.Length < 1) 
                    return;
                BindingPairs.ToList().ForEach(pair => Bind(pair.Key).To(pair.Value));
            }
            /// <summary>
            /// Gets/sets the dependency map.
            /// </summary>
            private KeyValuePair<Type, Type>[] BindingPairs { get; set; }
        }
        /// <summary>
        /// Frees managed and native resources.
        /// </summary>
        /// <param name="disposing">Disposes managed resource, <see cref="Core"/>, when true.</param>
        private void Dispose(bool disposing)
        {
            if (!disposing || Core == null)
                return;
            ConcreteCore.Dispose();
            Core = null;
        }
    }
}